package cc.yugu.yhdw.webserver.service.basic;

import cc.yugu.yhdw.common.constant.ConstEnum;
import cc.yugu.yhdw.common.constant.Constant;
import cc.yugu.yhdw.common.domain.basic.Agent;
import cc.yugu.yhdw.common.domain.basic.AgentInfo;
import cc.yugu.yhdw.common.domain.basic.User;
import cc.yugu.yhdw.common.domain.hdw.Agency;
import cc.yugu.yhdw.common.domain.hdw.AgencyInfo;
import cc.yugu.yhdw.common.domain.hdw.AgentHdwSetting;
import cc.yugu.yhdw.common.entity.AreaCache;
import cc.yugu.yhdw.common.entity.json.ExtResult;
import cc.yugu.yhdw.common.entity.pagination.Page;
import cc.yugu.yhdw.common.entity.tree.Node;
import cc.yugu.yhdw.common.entity.tree.NodeModel;
import cc.yugu.yhdw.common.utils.YhdwUtils;
import cc.yugu.yhdw.webserver.config.AppConfig;
import cc.yugu.yhdw.webserver.entity.SessionUser;
import cc.yugu.yhdw.webserver.persistence.basic.*;
import cc.yugu.yhdw.webserver.persistence.hdw.*;
import cc.yugu.yhdw.webserver.service.AbstractService;
import com.whalin.MemCached.MemCachedClient;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

/**
 * 运营商业务
 *
 * @Date:Created in 2018/7/3 9:42
 * @Author:
 * @Modified By: zjn 2018/7/3 9:42
 */
@Service
public class AgentService extends AbstractService {
    // 注入缓存客户端
    @Autowired
    MemCachedClient memCachedClient;
    @Autowired
    AppConfig config;
    @Autowired
    AgentMapper agentMapper;
    @Autowired
    SupplierMapper supplierMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    CabinetMapper cabinetMapper;
    @Autowired
    PassportMapper passportMapper;
    @Autowired
    MobileMessageTemplateMapper mobileMessageTemplateMapper;
    @Autowired
    SmsConfigMapper smsConfigMapper;
    @Autowired
    AgentHdwSettingMapper agentHdwSettingMapper;
    @Autowired
    AgencyMapper agencyMapper;
    @Autowired
    PlatformMapper platformMapper;
    @Autowired
    AgencyInOutMoneyMapper agencyInOutMoneyMapper;
    @Autowired
    AgentInOutMoneyMapper agentInOutMoneyMapper;
    @Autowired
    RescuerMapper rescuerMapper;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    DeptMapper deptMapper;
    @Autowired
    CabinetStrategyMapper cabinetStrategyMapper;
    @Autowired
    ExchangeAmountMoneyDivideMapper exchangeAmountMoneyDivideMapper;
    @Autowired
    ExchangeAmountMoneyDivideDetailMapper exchangeAmountMoneyDivideDetailMapper;
    @Autowired
    AreaCache areaCache;

    // zjn:新增两个查询方法
    /**
    * 查询运营商名称
    * 
    * @Param: [id]
    * @Return: cc.yugu.yhdw.common.domain.basic.AgentInfo
    * @Author By: zjn 2018/7/24  16:49
    */ 
    public AgentInfo findAgentName(int id){
        return agentMapper.findInfo(id);
    }
    /**
    * 查询代理商名称
    * 
    * @Param: [id]
    * @Return: cc.yugu.yhdw.common.domain.hdw.AgencyInfo
    * @Author By: zjn 2018/7/24  17:13
    */ 
    public AgencyInfo findAgencyName(int id){
        return agencyMapper.find(id);
    }

    /**
    * 根据主键获取向运营商信息，并根据信息获取地址
    * 
    * @Param: [id]
    * @Return: cc.yugu.yhdw.common.domain.basic.Agent
    * @Author By: zjn 2018/7/3  9:48
    */ 
    public Agent find(Integer id) {
        Agent agent = agentMapper.find(id);
        if (agent != null && agent.getParentId() != null && agent.getParentId() != 0) {
            agent.setParentIdName(agentMapper.find(agent.getParentId()) != null ? agentMapper.find(agent.getParentId()).getAgentName() : "");
        } else if (agent != null) {
            agent.setParentIdName("无");
        }

        return (Agent) setAreaProperties(areaCache, agent);
    }
    /**
    * 根据启用标识（1）查询表 bas_agent
    * 
    * @Param: []
    * @Return: java.util.List<cc.yugu.yhdw.common.domain.basic.Agent>
    * @Author By: zjn 2018/7/3  9:50
    */ 
    public List<Agent> findAll() {
        return agentMapper.findAll(ConstEnum.Flag.TRUE.getValue());
    }
    /**
    * 分页查询
    * 
    * @Param: [search]
    * @Return: cc.yugu.yhdw.common.entity.pagination.Page
    * @Author By: zjn 2018/7/3  9:50
    */ 
    public Page findPage(Agent search) {
        Page page = search.buildPage();
        page.setTotalItems(agentMapper.findPageCount(search));
        search.setBeginIndex(page.getOffset());
        List<Agent> list = agentMapper.findPageResult(search);
//        for (Agent agent : list) {
//            if (agent.getParentId() != null && agent.getParentId() != 0) {
//                agent.setParentIdName(agentMapper.find(agent.getParentId()) != null ? agentMapper.find(agent.getParentId()).getAgentName() : "");
//            } else {
//                agent.setParentIdName("无");
//            }
//        }
        page.setResult(list);
        return page;
    }
    /**
    * 插入（带回滚）
    *
    * @Param: [agent]
    * @Return: cc.yugu.yhdw.common.entity.json.ExtResult
    * @Author By: zjn 2018/7/3  9:51
    */
    @Transactional(rollbackFor = Throwable.class)
    public ExtResult insert(Agent agent) {
        try {
            // 设置创建时间
            agent.setCreateTime(new Date());
            // 设置余额
            agent.setBalance(0);
            // 将上级运营商设为null
            if (agent.getParentId() != null && agent.getParentId() == 0) {
                agent.setParentId(null);
            }
            agentMapper.insert(agent);

            AgentHdwSetting hdwSetting = new AgentHdwSetting();
            // 设置运营商 主键
            hdwSetting.setId(agent.getId());
            // 设置换电价格
            hdwSetting.setExchangePrice(5.0);
            agentHdwSettingMapper.insert(hdwSetting);

            String agentId = agent.getId().toString();
            for (String sql : config.mobileMessageTemplateSql) {
                // 更换内容，用 agentId 替换 "0/*agent_id*/"
                mobileMessageTemplateMapper.insert(sql.replace("0/*agent_id*/", agentId));
            }
        } catch (Exception e) {
            return ExtResult.failResult("新增失败");
        }
        return ExtResult.successResult();
    }
    /**
    * 根据主键更新
    *
    * @Param: [entity]
    * @Return: cc.yugu.yhdw.common.entity.json.ExtResult
    * @Author By: zjn 2018/7/3  10:17
    */
    public ExtResult update(Agent entity) {
        try {
            if (entity.getParentId() != null && entity.getParentId() == 0) {
                entity.setParentId(null);
            }
            agentMapper.update(entity);
        } catch (Exception e) {
            return ExtResult.failResult("修改失败");
        }
        return ExtResult.successResult();
    }
    /**
    * 更新各运营商数据
    * 
    * @Param: [sessionUser]
    * @Return: void
    * @Author By: zjn 2018/7/3  11:07
    */ 
    public void updateAgentData(SessionUser sessionUser) {
        // 创建一个新的字节数组输出流，缓冲区容量最初为32字节，但必要时其大小会增加。
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        String dummy = null;
        // 根节点集合，初始为空
        List<Node<NodeModel>> roots = Collections.EMPTY_LIST;
        Map<Object, String> agentMap = new HashMap<Object, String>();
        // 如果是代理商，设置运营商名称为 代理商名称
        if (sessionUser.getType() == User.Type.AGENCY.getValue()) {
            sessionUser.setAgentName(agencyMapper.find(sessionUser.getAgencyId()) != null ? agencyMapper.find(sessionUser.getAgencyId()).getAgencyName() : "");
            return;
        }
        // 设置运营商名称为厂商名称
        if (sessionUser.getType() == User.Type.SUPPLIER.getValue()) {
            sessionUser.setAgentName(supplierMapper.find(sessionUser.getSupplierId()) != null ? supplierMapper.find(sessionUser.getSupplierId()).getSupplierName() : "");
            return;
        }

        if (sessionUser.getId() == Constant.ADMIN_USER_ID) { //系统管理员
            dummy = platformMapper.find().getPlatformName();
            roots = buildTree(null, true/*显示代理商*/, dummy);
            sessionUser.setAgentName(dummy);

        } else if (sessionUser.isAdmin()) {
            roots = buildTree(sessionUser.getRootAgentId(), true/*显示代理商*/, dummy);
            sessionUser.setAgentName(agentMapper.find(sessionUser.getRootAgentId()) != null ? agentMapper.find(sessionUser.getRootAgentId()).getAgentName() : "");

        } else {
            sessionUser.setAgentName(agentMapper.find(sessionUser.getRootAgentId()) != null ? agentMapper.find(sessionUser.getRootAgentId()).getAgentName() : "");
        }

        if (!roots.isEmpty()) {
            try {
                tree(roots, stream);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            for (Node<NodeModel> root : roots) {
                buildNameMap(root, agentMap);
            }

            sessionUser.setAgentMap(agentMap);
            sessionUser.setAgentTree(stream.toByteArray());
        }
    }
    /**
    * 存储各层节点
    * 
    * @Param: [node, map]
    * @Return: void
    * @Author By: zjn 2018/7/3  11:31
    */ 
    private void buildNameMap(Node<NodeModel> node, Map<Object, String> map) {
        map.put(node.getData().getId(), node.getData().getName());

        for (Node<NodeModel> child : node.getChildren()) {
            buildNameMap(child, map);
        }
    }
    /**
    * 输出构建的目录树
    * 
    * @Param: [dummy, parentId, showAgency, stream]
    * @Return: void
    * @Author By: zjn 2018/7/3  11:32
    */ 
    public void tree(String dummy, Integer parentId, boolean showAgency, OutputStream stream) throws IOException {
        tree(buildTree(parentId, showAgency, dummy), stream);
    }

    private void tree(List<Node<NodeModel>> roots, OutputStream stream) throws IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        JsonGenerator json = objectMapper.getJsonFactory().createJsonGenerator(stream, JsonEncoding.UTF8);
        json.writeStartArray();
        YhdwUtils.writeJson(roots, json);
        json.writeEndArray();

        json.flush();
        json.close();
    }
    /**
    * 构建目录树
    * 
    * @Param: [parentId, showAgency, dummy]
    * @Return: java.util.List<cc.yugu.yhdw.common.entity.tree.Node<cc.yugu.yhdw.common.entity.tree.NodeModel>>
    * @Author By: zjn 2018/7/3  11:05
    */ 
    private List<Node<NodeModel>> buildTree(Integer parentId, boolean showAgency, String dummy) {
        // 获取一个空的set集合
        Set<Integer> checked = Collections.emptySet();

        List<Agent> agentList = agentMapper.findAll(ConstEnum.Flag.TRUE.getValue());
        Map<Integer, Agent> allMap = new HashMap<Integer, Agent>();
        List<Agent> topList = new ArrayList<Agent>();

        for (Agent agent : agentList) {
            // key-value 存储
            allMap.put(agent.getId(), agent);
            if (parentId == null) {
                if (agent.getParentId() == null) {
                    topList.add(agent);
                }
            } else {
                // 如果本身就是最上级
                if (agent.getId().equals(parentId)) {
                    topList.add(agent);
                }
            }
        }

        List<Node<NodeModel>> roots = new ArrayList<Node<NodeModel>>();
        if (StringUtils.isNotEmpty(dummy)) {
            NodeModel data = new NodeModel();
            Node<NodeModel> root = new Node<NodeModel>(data);
            data.setId(0);
            data.setName(dummy);
            roots.add(root);

            for (Agent topAgent : topList) {
                NodeModel nodeModel = new NodeModel();
                Node<NodeModel> node = new Node<NodeModel>(nodeModel, root);

                nodeModel.setId(topAgent.getId());
                nodeModel.setName(topAgent.getAgentName());
                nodeModel.setCheckStatus(checked.contains(topAgent.getId()) ? NodeModel.CheckedStatus.checked : NodeModel.CheckedStatus.unchecked);
                privateMakeTree(checked, node, showAgency, allMap, makeParentMap(allMap));
            }

        } else {
            for (Agent topAgent : topList) {
                NodeModel nodeModel = new NodeModel();
                Node<NodeModel> node = new Node<NodeModel>(nodeModel);

                nodeModel.setId(topAgent.getId());
                nodeModel.setName(topAgent.getAgentName());
                nodeModel.setCheckStatus(checked.contains(topAgent.getId()) ? NodeModel.CheckedStatus.checked : NodeModel.CheckedStatus.unchecked);
                privateMakeTree(checked, node, showAgency, allMap, makeParentMap(allMap));
                roots.add(node);
            }
        }

        return roots;
    }
    /**
    * 往父节点添加子节点
    * 
    * @Param: [checked, parent, showAgency, allMap, parentMap]
    * @Return: void
    * @Author By: zjn 2018/7/3  11:36
    */ 
    private void privateMakeTree(Set<Integer> checked, Node<NodeModel> parent, boolean showAgency, Map<Integer, Agent> allMap, Map<Integer, List<Integer>> parentMap) {
        List<Integer> sonIdList = parentMap.get(parent.getData().getId());
        if (sonIdList != null) {
            for (Integer id : sonIdList) {
                Agent agent = allMap.get(id);
                NodeModel nodeModel = new NodeModel();
                Node<NodeModel> node = new Node<NodeModel>(nodeModel);
                nodeModel.setId(agent.getId());
                nodeModel.setName(agent.getAgentName());
                nodeModel.setCheckStatus(checked.contains(agent.getId()) ? NodeModel.CheckedStatus.checked : NodeModel.CheckedStatus.unchecked);

                parent.addChild(node);

                privateMakeTree(checked, node, showAgency, allMap, parentMap);
            }
        }
        if (showAgency) {
            loadAgency(parent);
        }
    }
    /**
    * 构建父节点
    *
    * @Param: [agentMap]
    * @Return: java.util.Map<java.lang.Integer,java.util.List<java.lang.Integer>>
    * @Author By: zjn 2018/7/3  11:38
    */
    private Map<Integer, List<Integer>> makeParentMap(Map<Integer, Agent> agentMap) {
        Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
        for (Map.Entry<Integer, Agent> entry : agentMap.entrySet()) {
            if (entry.getValue().getParentId() != null) {
                Integer parentId = entry.getValue().getParentId();
                List<Integer> v = map.get(parentId);
                if (v == null) {
                    map.put(parentId, v = new ArrayList<Integer>());
                }
                v.add(entry.getKey());
            }
        }

        return map;
    }
    /**
    * 加载代理商信息
    *
    * @Param: [parent]
    * @Return: void
    * @Author By: zjn 2018/7/3  11:39
    */
    private void loadAgency(Node<NodeModel> parent) {
        NodeModel model = parent.getData();
        Integer agentId = (Integer) model.getId();
        // 根据运营商id 和 是否启用 标识 查询表hdw_agency
        List<Agency> agencyList = agencyMapper.findByAgent(agentId, ConstEnum.Flag.TRUE.getValue());
        for (Agency agency : agencyList) {
            NodeModel nodeModel = new NodeModel();
            Node<NodeModel> node = new Node<NodeModel>(nodeModel, parent);
            // 设置格式
            nodeModel.setId(String.format("agency-%d-%d", agentId, agency.getId()));
            nodeModel.setName("[代理商]" + agency.getAgencyName());
            nodeModel.setCheckStatus(NodeModel.CheckedStatus.unchecked);
        }
    }
    /**
    * 判断能否删除运营商
    * 
    * @Param: [agentId]
    * @Return: cc.yugu.yhdw.common.entity.json.ExtResult
    * @Author By: zjn 2018/7/3  11:52
    */ 
    private ExtResult hasRef(int agentId) {
        // 根据上级id（parent_id）统计表：bas_agent对应的行数量
        int amount = agentMapper.hasRecordByProperty("parentId", agentId);
        if (amount > 0) {
            return ExtResult.failResult("请先删除子运营商");
        }

//        amount = siteMapper.hasRecordByProperty("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("请先删除该运营商下网点");
//        }
//
//        amount = deptMapper.hasRecordByProperty("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商下含有部门不能删除");
//        }
//
//        amount = roleMapper.hasRecordByProperty("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商下含有角色不能删除");
//        }
        // 查询登录名称
        String username = userMapper.hasRecordByProperty("agentId", agentId);
        if (StringUtils.isNotEmpty(username)) {
            return ExtResult.failResult("该运营商下已有用户不能删除");
        }

//        amount = courierMapper.hasRecordByProperty("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商下已有快递员不能删除");
//        }
//
//        amount = terminalStrategyMapper.hasRecordByProperty("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商下已有终端策略,请选删除策略");
//        }
//
//        String msg = terminalMapper.hasRecordByProperty("agentId", agentId);
//        if(StringUtils.isNotEmpty(msg)) {
//            return ExtResult.failResult("该运营商下已有设备不能删除");
//        }

//        amount = hasRefSendOrder("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商已有订单,不能删除");
//        }
//
//        amount = hasRefDeliverOrder("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商已有订单,不能删除");
//        }
//
//        amount = hasRefStoreOrder("agentId", agentId);
//        if(amount > 0) {
//            return ExtResult.failResult("该运营商已有订单,不能删除");
//        }

        return ExtResult.successResult();
    }
    /**
    * 更新 是否启用 标识
    * 
    * @Param: [id, activeFlag]
    * @Return: cc.yugu.yhdw.common.entity.json.ExtResult
    * @Author By: zjn 2018/7/3  11:53
    */ 
    @Transactional(rollbackFor = Throwable.class)
    public ExtResult disable(int id, int activeFlag) {
//        ExtResult result = hasRef(id);
//        if (!result.isSuccess()) {
//            return result;
//        }
//        //部门 agent  agentsetting   角色   用户  短信配置
//        mobileMessageTemplateMapper.deleteByAgent(id);
//
//        smsConfigMapper.deleteByAgent(id);
//        agentMapper.delete(id);
//        agencyMapper.deleteByAgent(id);
//        agentHdwSettingMapper.delete(id);
//        memCachedClient.delete(CacheKey.key(CacheKey.K_ID_V_YKDG_SETTING, id));
//        memCachedClient.delete(CacheKey.key(CacheKey.K_ID_V_CHARGER_SETTING, id));
//        memCachedClient.delete(CacheKey.key(CacheKey.K_AGENT_ID_V_SMS_CONFIG_LIST, id));
//        memCachedClient.delete(CacheKey.key(CacheKey.K_ID_V_AGENT_INFO, id));
//        return ExtResult.successResult();
        try {
            agentMapper.disable(id, activeFlag);
            agencyMapper.disable(null, id, activeFlag);
            userMapper.disable(null, id, null, activeFlag);
            cabinetMapper.disable(null, id, activeFlag);
        } catch (Exception e) {
            return ExtResult.failResult("操作失败");
        }
        return ExtResult.successResult();
    }
    /**
    * 按条件删除不同表中的相关联的信息
    * 
    * @Param: [id]
    * @Return: cc.yugu.yhdw.common.entity.json.ExtResult
    * @Author By: zjn 2018/7/3  11:54
    */ 
    @Transactional(rollbackFor = Throwable.class)
    public ExtResult delete(int id) {
        try {
            agentMapper.delete(id);
            agencyMapper.deleteByAgent(id);
            agentInOutMoneyMapper.deleteByAgent(id);
            agencyInOutMoneyMapper.deleteByAgent(id);
            passportMapper.updateAgent(id);
            rescuerMapper.deleteByAgent(id);
            userMapper.deleteByAgent(id);
            roleMapper.deleteByAgent(id);
            deptMapper.deleteByAgent(id);
            cabinetMapper.deleteByAgent(id);
            cabinetStrategyMapper.deleteByAgent(id);
            agentHdwSettingMapper.delete(id);
            mobileMessageTemplateMapper.deleteByAgent(id);
            smsConfigMapper.deleteByAgent(id);
            exchangeAmountMoneyDivideDetailMapper.deleteByAgent(id);
            exchangeAmountMoneyDivideMapper.deleteByAgent(id);
        } catch (Exception e) {
            return ExtResult.failResult("操作失败");
        }
        return ExtResult.successResult();
    }
}
